"""
Mesh quality assessment module
"""
import numpy as np
try:
    import vtk
    VTK_AVAILABLE = True
except ImportError:
    VTK_AVAILABLE = False

class MeshQuality:
    """Class for assessing mesh quality"""
    
    @staticmethod
    def calculate_quality_metrics(mesh_data):
        """
        Calculate various quality metrics for a mesh
        
        Parameters:
        -----------
        mesh_data : dict
            Dictionary containing mesh data
            
        Returns:
        --------
        dict
            Dictionary containing quality metrics
        """
        if 'vtk_mesh' in mesh_data and VTK_AVAILABLE:
            return MeshQuality._calculate_vtk_quality_metrics(mesh_data['vtk_mesh'])
        else:
            return MeshQuality._calculate_manual_quality_metrics(mesh_data)
    
    @staticmethod
    def _calculate_vtk_quality_metrics(vtk_mesh):
        """Calculate quality metrics using VTK"""
        if not VTK_AVAILABLE:
            raise ImportError("VTK is not available. Install it with 'pip install vtk'")
        
        # Create quality filter
        quality_filter = vtk.vtkMeshQuality()
        quality_filter.SetInputData(vtk_mesh)
        
        # Set quality measures to compute
        quality_filter.SetTriangleQualityMeasureToAspectRatio()
        quality_filter.Update()
        
        # Get quality array
        quality_array = quality_filter.GetOutput().GetCellData().GetArray("Quality")
        
        # Convert to numpy array
        if quality_array:
            quality = np.array([quality_array.GetValue(i) for i in range(quality_array.GetNumberOfTuples())])
        else:
            quality = np.array([])
        
        # Calculate statistics
        metrics = {
            'min_quality': np.min(quality) if len(quality) > 0 else 0,
            'max_quality': np.max(quality) if len(quality) > 0 else 0,
            'avg_quality': np.mean(quality) if len(quality) > 0 else 0,
            'std_quality': np.std(quality) if len(quality) > 0 else 0,
            'quality_values': quality,
            'quality_type': 'aspect_ratio'
        }
        
        return metrics
    
    @staticmethod
    def _calculate_manual_quality_metrics(mesh_data):
        """Calculate quality metrics manually"""
        points = mesh_data['points']
        cells = mesh_data['cells']
        
        # Calculate aspect ratio for triangles
        aspect_ratios = []
        
        for cell in cells:
            if len(cell) == 3:  # Triangle
                p1, p2, p3 = points[cell[0]], points[cell[1]], points[cell[2]]
                
                # Calculate edge lengths
                a = np.linalg.norm(p2 - p1)
                b = np.linalg.norm(p3 - p2)
                c = np.linalg.norm(p1 - p3)
                
                # Calculate semi-perimeter
                s = (a + b + c) / 2
                
                # Calculate area using Heron's formula
                area = np.sqrt(s * (s - a) * (s - b) * (s - c))
                
                # Calculate aspect ratio (circumradius to inradius ratio)
                if area > 1e-10:  # Avoid division by zero
                    inradius = area / s
                    circumradius = (a * b * c) / (4 * area)
                    aspect_ratio = circumradius / inradius
                else:
                    aspect_ratio = float('inf')
                
                aspect_ratios.append(aspect_ratio)
        
        aspect_ratios = np.array(aspect_ratios)
        
        # Calculate statistics
        metrics = {
            'min_quality': np.min(aspect_ratios) if len(aspect_ratios) > 0 else 0,
            'max_quality': np.max(aspect_ratios) if len(aspect_ratios) > 0 else 0,
            'avg_quality': np.mean(aspect_ratios) if len(aspect_ratios) > 0 else 0,
            'std_quality': np.std(aspect_ratios) if len(aspect_ratios) > 0 else 0,
            'quality_values': aspect_ratios,
            'quality_type': 'aspect_ratio'
        }
        
        return metrics
    
    @staticmethod
    def identify_poor_quality_elements(mesh_data, threshold=2.0):
        """
        Identify elements with poor quality
        
        Parameters:
        -----------
        mesh_data : dict
            Dictionary containing mesh data
        threshold : float
            Quality threshold (elements with quality > threshold are considered poor)
            
        Returns:
        --------
        list
            Indices of poor quality elements
        """
        quality_metrics = MeshQuality.calculate_quality_metrics(mesh_data)
        quality_values = quality_metrics['quality_values']
        
        # Find elements with quality worse than threshold
        poor_elements = np.where(quality_values > threshold)[0].tolist()
        
        return poor_elements 